package com.yonyou.pmclouds.basecom.util;

import com.yonyou.iuap.security.esapi.EncryptException;
import com.yonyou.iuap.security.utils.TokenGenerator;
import com.yonyou.pmclouds.basecom.conf.NCCStorageProperties;
import com.yonyou.pmclouds.basecom.exception.BusinessRuntimeException;
import com.yonyou.yht.sdk.SessionStoreFactory;
import com.yonyou.yht.utils.SdkUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * NCC 后端文件工具类
 */
@Component
public class NCCFileStorageUtil extends AbstractStorageUtil {

    public static final String FILE_URI = "/rest/file";

    @Autowired
    private NCCStorageProperties nccStorageProperties;

    @Override
    public Map<String, String> getSignWithDir(String dir, HttpServletRequest request) {
        Map<String, String> respMap = new LinkedHashMap<>();
        respMap.put("dir", dir);
        String host = getEndpoint(request) + "/file/upload";
        respMap.put("host", host);

        /**
         * token for mobile only.
         * As web client use cookie based YHT authentication,
         * there is no token can get from request thus no token will be added here for web post.
         */
        String token = getToken(request);
        if(token != null)
            respMap.put("Authorization", "Bearer " + token);
        return respMap;
    }

    /**
     * 当使用友工程web端时， 由于是跳转到友互通页面做login操作， 登录信息只存在cookie当中，
     * cookie信息无法绑定到url上， 故此处生成url不再能够做到‘生成一次， 任何地方均可访问’。
     * 现将文件下载路径改成"/rest/file", 以跳过登录验证
     *
     * Assume no auth required for download the file for now.
     * TODO 添加图片下载非友互通功能验证。
     * @param pic
     * @param process
     * @param request
     * @return
     */
    @Override
    public String signUrlForSingleAppPic(String pic, String process, HttpServletRequest request) {
        String url = getEndpoint(request) + FILE_URI + "/";

        if (!pic.startsWith("app/") && !pic.startsWith("web/"))
            pic = "app/" + pic;

        /*try {
            url += URLEncoder.encode(pic, "utf-8").replace("+", "%20");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Unexpected encoding error. ", e);
        }*/

        if(nccStorageProperties.getValidateToken()) {
            long ts = System.currentTimeMillis();
            String token = sign(pic, ts);
            return url + pic+"?ts=" + ts + "&tk=" + token;
        }else
            return url + pic;


    }

    public String sign(String path, long timestamp){
        try {
            String token =  TokenGenerator.genToken(path, timestamp, SessionStoreFactory.getSessionStore().findSeed());
            return token.replaceAll("[^A-Z0-9a-z]+", "");
        } catch (EncryptException e) {
            throw new BusinessRuntimeException(e);
        }
    }

    private String getEndpoint(HttpServletRequest request){
        /** In case there are some proxy or router impacting on the final path,
         *  then we can switch to the backup path instead.*/
        if(nccStorageProperties.getUseBackupPath())
            return nccStorageProperties.getBackupServerPath();

        return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
    }

    private String getToken(HttpServletRequest request){
        String token = SdkUtils.retrieveAccessToken(request);
        if(token == null )//capable for mobile client
            token = request.getHeader("access-token");
        if(token == null )
            token = request.getParameter("access-token");

        return token;
    }

    @Override
    public long getFileContentLength(String path) {
        String url = nccStorageProperties.getEndpoint() + "/pmbd/pmcloud/fileStorage?method=describe&ds=" + nccStorageProperties.getDatasource() + "&path=";
        try {
            url = url + URLEncoder.encode(path, "utf-8").replace("+","%20");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = null;
        BufferedReader reader = null;
        Long size = 0L;

        try {
            httpGet = new HttpGet(url);
            CloseableHttpResponse getResponse = httpClient.execute(httpGet);

            reader = new BufferedReader(new InputStreamReader(getResponse.getEntity().getContent()));
            String str;
            while((str = reader.readLine()) != null){
                if(str.startsWith("size=")) {
                    size = Long.parseLong(str.substring(str.indexOf("=") + 1));
                    break;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if(reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return size;
    }
}
